package dper.study.codes.concurrent.service;

import dper.study.codes.concurrent.api.JKXYConcurrentTutorialAPI;
import dper.study.codes.concurrent.model.*;
import dper.study.codes.concurrent.worker.Consumer;
import dper.study.codes.concurrent.worker.Producer;
import dper.study.codes.concurrent.worker.SimpleThread;
import org.apache.log4j.Logger;

/**
 * Created by leichen on 2017/3/20.
 */
public class JKXYConcurrentTutorialService implements JKXYConcurrentTutorialAPI{
    Logger logger = Logger.getLogger(JKXYConcurrentTutorialService.class) ;

    public int simpleMultiThread() {
        Runnable runnable = new Runnable(){
            private int ticketNum =5 ;
            public synchronized void  run() {
                if(ticketNum > 0)
                        ticketNum -- ;
                logger.info("Runnable\t"+ Thread.currentThread() + "\t" + ticketNum); ;
            }
        } ;
        final Thread thread1 = new Thread(runnable) ;
        thread1.start() ;
        Thread thread2 = new Thread(runnable) ;
        thread2.start() ;
        Thread thread3 = new Thread(runnable) ;
        thread3.start() ;
        Thread thread4 = new Thread(runnable) ;
        thread4.start() ;
        Thread thread5 = new Thread(runnable) ;
        thread5.start() ;
        try {
            thread1.join();
            thread2.join();
            thread3.join();
            thread4.join();
            thread5.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread thread6 = new SimpleThread() ;
        thread6.start();
        Thread thread7 = new SimpleThread() ;
        thread7.start();
        Thread thread8 = new SimpleThread() ;
        thread8.start();
        try {
            thread6.join();
            thread7.join();
            thread8.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Runnable runnable_volatile = new Runnable(){
            private volatile int ticketNum = 5 ;

            public int readNum(){
                logger.info("runnable_volatile\t"+Thread.currentThread()+"\t"+ticketNum);
                return ticketNum ;
            }

            public synchronized void writeNum(){
                ticketNum -- ;
            }
            public void run() {
                writeNum() ;
                readNum() ;
            }
        }  ;
        new Thread(runnable_volatile).start();
        new Thread(runnable_volatile).start();
        new Thread(runnable_volatile).start();
        new Thread(runnable_volatile).start();
        new Thread(runnable_volatile).start();

        return 0 ;
    }

    public int simpleWaitNotify() {
        ProConBuffer proConBuffer = new ProConBufferWaitNotifyAll();
        Consumer consumer = new Consumer(proConBuffer) ;
        new Thread(consumer).start();
        new Thread(consumer).start();

        Producer producer = new Producer(proConBuffer) ;
        new Thread(producer).start();
        new Thread(producer).start();
        new Thread(producer).start();

        return 0;
    }

    public int simpleReentrantLockAndCondition() {
        ProConBuffer proConBuffer = new ProConBufferLockAndCondition();
        Consumer consumer = new Consumer(proConBuffer) ;
        new Thread(consumer).start();
        new Thread(consumer).start();

        Producer producer = new Producer(proConBuffer) ;
        new Thread(producer).start();
        new Thread(producer).start();
        new Thread(producer).start();

        return 0;
    }

    public int simpleBlockingQueue() {
        ProConBuffer proConBuffer = new ProConBufferBlockQueue();
        Consumer consumer = new Consumer(proConBuffer) ;
        new Thread(consumer).start();
        new Thread(consumer).start();

        Producer producer = new Producer(proConBuffer) ;
        new Thread(producer).start();
        new Thread(producer).start();
        new Thread(producer).start();

        return 0;
    }

    public int simpleSemaphore() {
        ProConBuffer proConBuffer = new ProConBufferSemaphore();
        Consumer consumer = new Consumer(proConBuffer) ;
        new Thread(consumer).start();
        new Thread(consumer).start();

        Producer producer = new Producer(proConBuffer) ;
        new Thread(producer).start();
        new Thread(producer).start();
        new Thread(producer).start();
        return 0;
    }


    public static void main(String[] argv){
        JKXYConcurrentTutorialAPI jkxyConcurrentTutorialAPI = new JKXYConcurrentTutorialService() ;
        jkxyConcurrentTutorialAPI.simpleSemaphore() ;
    }
}
